package com.csust.automaticteach.app.agent;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.csust.automaticteach.app.agent.model.AgentState;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.ToolResponseMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.ToolCallingManager;
import org.springframework.ai.model.tool.ToolExecutionResult;
import org.springframework.ai.tool.ToolCallback;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassNameToolCallAgent
 * @Description 工具调用 代理
 * @Author钰玟
 * @Date2025/6/17 下午10:04
 * @Version 1.0
 **/
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
@NoArgsConstructor
public class ToolCallAgent extends ReActAgent {
    /**
     * 提供的工具集合
     */
    private ToolCallback[] availableTools;
    /**
     * 工具调用的响应
     */
    private ChatResponse toolCallChatResponse;
    /**
     * 工具调用管理器
     */
    private ToolCallingManager toolCallingManager;
    /**
     * 聊天选项 用于关闭  Spring AI 的默认工具调用
     */
    private ChatOptions chatOptions;

    public ToolCallAgent(ToolCallback[] allTools) {
        super();
        this.availableTools = allTools;
        this.toolCallingManager = ToolCallingManager.builder().build();
        //设置withProxyToolCalls(true) 关闭 Spring AI 的默认工具调用
        this.chatOptions = DashScopeChatOptions.builder()
                .withProxyToolCalls(true)
                .build();
    }

    @Override
    public boolean think() {
        if (getNextStepPrompt() != null && StrUtil.isNotBlank(getNextStepPrompt())) {
            //判断下一步提示词不为空,,将其加入到用户消息中
            getMessageList().add(new UserMessage(getNextStepPrompt()));
        }
        List<Message> messageList = getMessageList();
        Prompt prompt = new Prompt(messageList, chatOptions);
        //调用ai大模型
        try {
            ChatResponse chatResponse = getChatClient().prompt(prompt)
                    .tools(availableTools)//工具
                    .call()
                    .chatResponse();
            toolCallChatResponse = chatResponse;
            AssistantMessage assistantMessage = toolCallChatResponse.getResult().getOutput();
            //获取ai的输出
            String result = assistantMessage.getText();
            log.info("the AI's think is :{}", result);
            //获取所需要的工具调用的工具列表
            List<AssistantMessage.ToolCall> needToolCalls = assistantMessage.getToolCalls();
            log.info("the need tool calls are :{}", needToolCalls);
            //transform
            String toolInfo = needToolCalls.stream()
                    .map(toolCall -> String.format("the tool name :%s,args:%s", toolCall.name(), toolCall.arguments()))
                    .collect(Collectors.joining("\n"));
            //log
            log.info("the toolInfo :{}", toolInfo);
            if (CollUtil.isEmpty(needToolCalls)) {
                //只有未调用工具是，才需要记录会话上下文
                messageList.add(assistantMessage);
                return false;
            } else {
                //否则，无需记录上席文信息
                return true;
            }
        } catch (Exception e) {
            log.error("error to think or act,the reason is :" + e.getMessage());
            //无需抛出异常，大模型会自动重试
//            throw new BusinessException(ErrorCode.SYSTEM_ERROR,SYSTEM_IS_BUSY); 如果抛出异常，则无法重试
            //将异常消息添加至会话上下文中
            messageList.add(new AssistantMessage(e.getMessage()));
            return false;
        }
    }

    @Override
    public String act() {
        //1.判断是否需要工具调用
        if (!toolCallChatResponse.hasToolCalls()) {
            return "No tools to act";
        }
        //2.有，判断是否有所需要的工具调用
        Prompt prompt = new Prompt(getMessageList(), chatOptions);
        //2.1执行工具调用
        ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(prompt, toolCallChatResponse);
        //2.2获取上下文
        List<Message> messages = toolExecutionResult.conversationHistory();
        //2.3 设置上下文
        setMessageList(messages);
        //3.获取助手消息===最后一条即为助手回复的消息
        ToolResponseMessage assistant = (ToolResponseMessage) CollUtil.getLast(messages);
        String results = assistant.getResponses().stream()
                .map(response -> response.name() + "complete its task ! the result is :"
                        + response.responseData()
                ).collect(Collectors.joining("\n"));

        boolean isTerminated = assistant.getResponses().stream()
                .anyMatch(response -> ("doTerminate").equals(response.name()));
        if (isTerminated) {
            //终止
            setState(AgentState.FINISHED);
        }
        log.info("the tool call result is :{}", results);
        return results;
    }
}
